package com.darwin.darwinIsometric.pathfinding
{
	import flash.utils.Dictionary;

	/**
	 *	地图描述 
	 * @author Roland
	 * 
	 */
	public class MapGrid
	{
		/**
		 *	标记此张地图为适合几格物体寻路的. 如：2表示适合2x2物体寻路 
		 */
		public var enlargeValue:int = 1;
		
		private var _startNode:ANode;
		private var _endNode:ANode;
		private var _nodes:Array;
		private var _numCols:int;
		private var _numRows:int;
		
		private var _startX:int = 0;
		private var _startY:int = 0;
		
		private var _type:int;
		private var _straightCost:Number = 1.0;
		private var _diagCost:Number = Math.SQRT2;
		private var _maxConst:Number = 1000;
		public function MapGrid(numCols:int, numRows:int,startX:int=0,startY:int=0){
			_numCols = numCols;
			_numRows = numRows;
			_startX = startX;
			_startY = startY;
			_nodes = new Array();
			for (var i:int = 0; i < _numCols; i++){
				_nodes[i] = new Array();
				for (var j:int = 0; j < _numRows; j++){
					_nodes[i][j] = new ANode(i, j);
				}
				
			}
		}
		
		
		public function get startX():int
		{
			return _startX;
		}
		
		public function get startY():int
		{
			return _startY;
		}

		
		public function getNode(x:int, y:int):ANode {
			return _nodes[x][y];
		}
		
		public function setEndNode(x:int, y:int):void {
			if(_nodes[x-startX]!=null && _nodes[x-startX][y-startY]!=null)
			{
				_endNode = _nodes[x-startX][y-startY];
			}
		}
		
		public function setStartNode(x:int, y:int):void {
			if(_nodes[x-startX]!=null && _nodes[x-startX][y-startY]!=null)
			{
				_startNode = _nodes[x-startX][y-startY];
			}
		}
		
		public function setWalkable(x:int, y:int, value:int):void {
			_nodes[x][y].walkable = value;
			_nodes[x][y].changed = true;
		}
		
		public function getWalkable(x:int,y:int):int{
			var aNode:ANode;
			if(_nodes[x] && _nodes[x][y])
			{
				aNode = _nodes[x][y];
			}
			if(aNode)
			{
				return aNode.walkable;
			}
			return 0;
		}
		
		public function get endNode():ANode {
			return _endNode;
		}
		
		public function get numCols():int {
			return _numCols;
		}
		
		public function get numRows():int {
			return _numRows;
		}
		
		public function get startNode():ANode {
			return _startNode;
		}
		
		public function clone():MapGrid
		{
			var $map:MapGrid = new MapGrid(_numCols,_numRows);
			for(var i:int = 0;i<_numCols;i++)
			{
				for(var j:int = 0;j < _numRows; j++)
				{
					$map.setWalkable(i,j,getNode(i,j).walkable);
				}
			}
			if(startNode){
				$map.setStartNode(startNode.x,startNode.y);
			}
			if(endNode)
			{
				$map.setEndNode(endNode.x,endNode.y);
			}
			return $map;
		}
		
		
		/**
		 * 计算每个Anode相关联的Anode （可以通行的Anode）
		 * @param	type	0八方向 1四方向 2跳棋
		 */
		public function calculateLinks(type:int = 0):void {
			this._type = type;
			for (var i:int = 0; i < _numCols; i++){
				for (var j:int = 0; j < _numRows; j++){
					initNodeLink(_nodes[i][j]);
				}
			}
		}
		
		/**
		 *
		 * @param	type	0八方向 1四方向 2跳棋
		 */
		public function get type():int {
			return _type;
		}

		/**
		 * 初始化ANode的周围关联可以通行的关系（添加ANode层级的判断tier）
		 * @param	node  
		 */
		private function initNodeLink(node:ANode):void {
			var startX:int = Math.max(0, node.x - 1);
			var endX:int = Math.min(numCols - 1, node.x + 1);
			var startY:int = Math.max(0, node.y - 1);
			var endY:int = Math.min(numRows - 1, node.y + 1);
			node.links = [];
			
			for (var i:int = startX; i <= endX; i++){
				for (var j:int = startY; j <= endY; j++){
					var test:ANode = getNode(i, j);
					var cost:Number = _straightCost;
					if (test == node || !test.walkable ||  Math.abs(test.tier-node.tier)>1){
						node.links.push(new ALink(test, _maxConst));
						continue;
					}
					if (type != 2 && i != node.x && j != node.y){
						var test2:ANode = getNode(node.x, j);
						if (!test2.walkable || Math.abs(test2.tier-node.tier)>1 || test2.tier != node.tier){
							node.links.push(new ALink(test, _maxConst));
							continue;
						}
						test2 = getNode(i, node.y);
						if (!test2.walkable || Math.abs(test2.tier-node.tier)>1 || test2.tier != node.tier){
							node.links.push(new ALink(test, _maxConst));
							continue;
						}
					}
					
					if (!((node.x == test.x) || (node.y == test.y))){
						if (type == 1){//四个方向
							continue;
						}
						if (type == 2 && (node.x - test.x) * (node.y - test.y) == 1){
							node.links.push(new ALink(test, _maxConst));
							continue;
						}
						if (type == 2){
							cost = _straightCost;
						} else {
							cost = _diagCost;
						}
					}
					cost += cost* Math.abs(test.tier-node.tier); 
					node.links.push(new ALink(test, cost));
				}
			}
		}
		
		
		public function toString():String
		{
			var s:String = "";
			
			for(var j:int = 0;j<_numCols;j++)
			{
				for(var i:int = 0;i<_numRows;i++)
				{
					if(_nodes[i] && _nodes[i][j])
					{
						if((_nodes[i][j] as ANode).walkable == 0)
						{
							s += "@";
						}else if((_nodes[i][j] as ANode).walkable > 1){
							s += "+";
						}else{
							s += "0";
						}
					}else{
						break;
					}
				}
				s += "\n";
			}
			return s;
		}

		
	}
}